﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Forms;
using System.IO;
using System.IO.Compression;
using System.ComponentModel;
using System.Drawing;
using System.Diagnostics;
using Microsoft.DeepZoomTools;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using Cartoons.Model;

namespace BookComposer
{
    public partial class MainWindow : Window
    {
        string _tempDirectory = @"C:\temp";
        bool _CrateNullPage = true;

        public MainWindow()
        {
            InitializeComponent();
        }

        List<string> _titlePath = new List<string>();

        private void RunClick(object sender, RoutedEventArgs e)
        {
           // btRun.IsEnabled = false;
        
            var imagesRootDir = C_TextIn.Text;
            var outputDir = C_TextOut.Text;

            int bookSizeUpperBound;
            if (!int.TryParse(tbxUpperBound.Text, out bookSizeUpperBound))
            {
                System.Windows.MessageBox.Show("Incorrect upper bound");
                return;
            }

            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += (o, ea) =>
                {
                    AddElements(imagesRootDir, outputDir,null);
                };
            bw.RunWorkerAsync();
        }

        private void AddElements(string imagesRootDir, string outputDir,string imageDirectory)
        {
            _titlePath = new List<string>();
            _CrateNullPage = true;
            if (Directory.Exists(imagesRootDir))
            {
                short currBook = 0;
                foreach (var item in Directory.GetDirectories(imagesRootDir))///Получаем все папки с книгами
                {
                    if (Directory.GetFiles(item, "*.xml").Count() != 0)///Проверка есть ли xml файл
                    {
                        //var book = db.Books.OrderByDescending(b => b.TitlePageIndex).Where(b => !b.DzcFileLocation.EndsWith(".xml")).Skip(currBook).FirstOrDefault();
                        var imagesFolders = string.Format("{0}\\images", item);
                        if (Directory.Exists(imagesFolders))
                        //  foreach (var bookData in Directory.GetFiles(imagesFolders))
                        {
                            string fullFilePach = System.IO.Path.Combine(imagesFolders, item);

                            var count = Directory.GetFiles(imagesFolders).Count().ToString();

                            Dispatcher.Invoke(new Action(() =>
                                tbxBook.Text = Directory.GetFiles(imagesFolders).Count().ToString()));

                            Dispatcher.Invoke(new Action(() =>
                                tbxStatus.Text = string.Format("Checking size for {0} ({1})", imagesFolders, count)));

                            try
                            {
                                LoadBook(System.IO.Path.Combine(imagesRootDir, item), outputDir);
                                this.Dispatcher.Invoke(new Action(() => { booksProgress.Value++; }));
                                // book.DzcFileLocation = string.Format(@"{0:d7}/{1:d7}.xml", bookData.Name, bookData.Name);
                                // db.SaveChanges();
                            }
                            catch (Exception ex)
                            {
                                System.Windows.MessageBox.Show(ex.Message);
                            }

                        }


                        #region Вносим в базу данные о книге
                        BooksXMLHelper.ParseXMLFolder(item, currBook++);
                        #endregion

                        ///Проверяем наличие тайтла в папке
                        if (Directory.GetFiles(item, "*.jpg").Count() != 0)
                        {///Тайтел есть, можно его добавить 
                            _titlePath.Add(Directory.GetFiles(item, "*.jpg").FirstOrDefault());
                        }
                        else
                        {///Тайтла нету, нужно добавить первую картинку
                            string imageTitle = Directory.GetFiles(imagesFolders).First(p => p != "0.jpg");
                            _titlePath.Add(imageTitle);
                        }
                    }
                    else
                    {
                        System.Windows.MessageBox.Show(item + " не содержит xml файл, папка будет пропущена.");
                    }

                }

                #region Генерация Title
               
                if (!string.IsNullOrEmpty(imageDirectory))///Значит добавление элементов, нужно добавить старые обложки для генерации коректного тайтла
                    foreach (var item in Directory.GetFiles(imageDirectory,"*.jpg"))
                        _titlePath.Add(item);

                var tempDirNoIm = Directory.CreateDirectory(_tempDirectory + "\\title");
                var tempDir = Directory.CreateDirectory(_tempDirectory + "\\title\\images");
                var imageDir = Directory.CreateDirectory(outputDir + "\\title_image");

                ///Копируем тайтлы
                foreach (var item in _titlePath)
                {
                    var fileInfo = new FileInfo(item);
                    ///Копируем все тайтлы в temp папку
                    File.Copy(item, System.IO.Path.Combine(tempDir.FullName, fileInfo.Name));

                    File.Copy(item, System.IO.Path.Combine(imageDir.FullName, fileInfo.Name));
                }
                _CrateNullPage = false;
                LoadBook(tempDirNoIm.FullName, System.IO.Path.Combine(outputDir, "title"));

                #endregion
            }
            System.Windows.MessageBox.Show("Completed");
        }

        private void LoadBook(string inputDir, string outputDir)
        {
            var name = new DirectoryInfo(inputDir).Name;

            string imageFolder = inputDir + "\\images";

            var tempDir = Directory.CreateDirectory(_tempDirectory);
            // var tempDir = inputDir;

            Dispatcher.Invoke(new Action(() =>
                tbxStatus.Text = "Unzip images"));

            //var zipFolder = Unzip(tiffs, System.IO.Path.Combine(tempDir.FullName, "zip", name));
            //var zipFolder = Unzip(tiffs, System.IO.Path.Combine(tempDir.FullName, "zip", name));
            var convertedFolder = ConvertSizes(imageFolder, System.IO.Path.Combine(tempDir.FullName, name));
            ///Создание из картинок deepzoom колекции
            CreateDZC(convertedFolder, System.IO.Path.Combine(outputDir, name, name));
            Dispatcher.Invoke(new Action(() =>
                tbxStatus.Text = "Done"));
            Directory.Delete(tempDir.FullName, true);
        }

        private string Unzip(string[] files, string outputDir)
        {
            Directory.CreateDirectory(outputDir);
            int i = 0;
            foreach (var file in files)
            {
                try
                {
                    ProcessStartInfo psi = new ProcessStartInfo(
                        System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"7-zip\7z.exe"),
                        string.Format("x -o\"{0}\" \"{1}\"", outputDir, file));
                    var pr = Process.Start(psi);
                    pr.WaitForExit();
                    i++;
                }
                catch (Exception e)
                {
                    System.Windows.MessageBox.Show(e.Message);
                }
            }
            return outputDir;
        }

        /// <summary>
        /// Изменение размера и создание альтернативной картики с подресованными краями
        /// </summary>
        /// <param name="inputDir">Откуда брать картинку</param>
        /// <param name="outputDir">Куда сохранять</param>
        /// <returns>Путь к папке с сохраненными картинками</returns>
        private string ConvertSizes(string inputDir, string outputDir)
        {
            Directory.CreateDirectory(outputDir);
            var files = Directory.GetFiles(inputDir);
            Dispatcher.Invoke(new Action(() => { pagesProgress.Maximum = files.Count() * 3; pagesProgress.Value = 0; }));
            ///Самое большое соотношение Height / Width;
            double asp = 0;
            int i = 0;
            ///Получаем самое большое соотношение высоты к ширене 
            foreach (var file in files)
            {
                System.Drawing.Image img = System.Drawing.Image.FromFile(file);
                GC.Collect();
                Dispatcher.Invoke(new Action(() => { tbxStatus.Text = "Check size for " + file; pagesProgress.Value++; }));
                double a = img.Height / (double)img.Width;
                asp = Math.Max(a, asp);
                i++;
            }
            i = 0;

            if (_CrateNullPage)
            {
                ///Создаем обложку
                Bitmap transparent = new Bitmap(100, (int)(asp * 100));
                Graphics gr = Graphics.FromImage(transparent);
                gr.FillRectangle(System.Drawing.Brushes.Transparent, 0, 0, transparent.Width, transparent.Height);
                transparent.Save(System.IO.Path.Combine(outputDir, "0.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
            }

            ///Теперь рисуем картинки
            foreach (var file in files)
            {
                var image = System.Drawing.Image.FromFile(file);
                Bitmap b = new Bitmap(image.Width, (int)(asp * image.Width));
                Graphics g = Graphics.FromImage(b);
                g.FillRectangle(System.Drawing.Brushes.White, 0, 0, b.Width, b.Height);
                g.DrawImage(image, 0, 0, image.Width, image.Height);
                FileInfo f = new FileInfo(file);
                b.Save(System.IO.Path.Combine(outputDir, f.Name), System.Drawing.Imaging.ImageFormat.Jpeg);
                Dispatcher.Invoke(new Action(() => { tbxStatus.Text = "Convert size for " + file; pagesProgress.Value++; }));
                i++;
            }
            return outputDir;
        }


        private void CreateDZC(string inputDir, string outputDir)
        {
            ///Получаем количество картинок в папке книги
            var filesCount = Directory.GetFiles(inputDir).Count();
            ///Время создания коллекии картинок
            var timer = RunProgressTimer(outputDir, filesCount * 2, filesCount, pagesProgress);

            CollectionCreator col = new CollectionCreator();
            col.ConversionImageQuality = 1;
            col.ConversionTileFormat = ImageFormat.Png;
            col.ImageQuality = 1;
            col.UseOptimizations = true;
            col.Create(Directory.GetFiles(inputDir).Select(f => new Microsoft.DeepZoomTools.Image(f)).ToArray(), outputDir);
            Dispatcher.Invoke(new Action(() => { if (timer != null) timer.Stop(); }));
        }

        private System.Windows.Threading.DispatcherTimer RunProgressTimer(string outputDir, int initialState, int totalProgress, System.Windows.Controls.ProgressBar progressDisplay)
        {
            System.Windows.Threading.DispatcherTimer timer = null;
            Dispatcher.Invoke(new Action(() =>
            {
                timer = new System.Windows.Threading.DispatcherTimer();
                timer.Tick += (o, e) =>
                {
                    try
                    {
                        var processedCount = Directory.GetFiles(outputDir + "_images").Count();
                        progressDisplay.Value = initialState + processedCount;
                        if (processedCount > 0)
                            tbxStatus.Text = "Create dzc for " + Directory.GetFiles(outputDir + "_images").Last();
                    }
                    catch { }
                };
                timer.Interval = new TimeSpan(0, 0, 2);
                timer.Start();
            }));
            return timer;
        }

        private void btUpdateTitles_Click(object sender, RoutedEventArgs e)
        {
           // btRun.IsEnabled = false;

            var imagesRootDir = C_TextInAdd.Text;
            var outputDir = C_TextOutAdd.Text;
            var titleDir = C_TextImageAdd.Text;

            int bookSizeUpperBound;
            if (!int.TryParse(tbxUpperBound.Text, out bookSizeUpperBound))
            {
                System.Windows.MessageBox.Show("Incorrect upper bound");
                return;
            }

            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += (o, ea) =>
            {
                AddElements(imagesRootDir, outputDir, titleDir);
            };
            bw.RunWorkerAsync();
        }


        private string[] GetBookFolderPath(string input)
        {
            int unused;
            return input.Split(';').Where(s => !string.IsNullOrEmpty(s)).Where(s => int.TryParse(s, out unused)).Select(s => string.Format("{0:d7}", int.Parse(s))).ToArray();
        }

        private void UIThread(Action action)
        {
            Dispatcher.Invoke(action);
        }

        private void C_In_Click(object sender, RoutedEventArgs e)
        {
            FolderPatch(C_TextIn);
        }

        private void C_Out_Click(object sender, RoutedEventArgs e)
        {
            FolderPatch(C_TextOut);
        }

        ///Окошко диалога выбора папки, путь пишем в TextBox
        private string FolderPatch(System.Windows.Controls.TextBox box)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                box.Text = dialog.SelectedPath;
                return dialog.SelectedPath;
            }
            return null;
        }

        private void C_Image_Click(object sender, RoutedEventArgs e)
        {
            FolderPatch(C_TextImageAdd);
        }




        //private void btUpdateTitles_Click(object sender, RoutedEventArgs e)
        //{
        //    var input = C_TextIn.Text;
        //    var output = C_TextOut.Text;
        //    BackgroundWorker worker = new BackgroundWorker();
        //    worker.DoWork += (o, ea) =>
        //    {
        //        var db = new BooksDBEntities();
        //        var titles = db.Books
        //            .Where(b => b.TitlePageIndex >= 0)
        //            .OrderBy(b => b.TitlePageIndex).ToArray()
        //            .Select(b => GetBookFolderPath(b.InputFilesFolder).Single())
        //            .Select(f => System.IO.Path.Combine(input, f, "title.jpg"))
        //            .ToList();

        //        var newBooks = db.Books
        //            .Where(b => b.TitlePageIndex < 0).ToArray()
        //            .Where(b => GetBookFolderPath(b.InputFilesFolder).Any(f => File.Exists(System.IO.Path.Combine(input, f, "title.jpg"))));

        //        foreach (var book in newBooks)
        //        {
        //            var folder = GetBookFolderPath(book.InputFilesFolder).Single(f => File.Exists(System.IO.Path.Combine(input, f, "title.jpg")));
        //            var path = System.IO.Path.Combine(input, folder, "title.jpg");
        //            titles.Add(path);
        //            book.TitlePageIndex = (short)titles.IndexOf(path);
        //            book.InputFilesFolder = folder + ";";
        //        }

        //        db.SaveChanges();

        //        var outputDir = System.IO.Path.Combine(output, "Titles", "Titles");

        //        // UIThread(() => pbTitlesUpdateProgress.Maximum = titles.Count());

        //        // var timer = RunProgressTimer(outputDir, 0, titles.Count(), pbTitlesUpdateProgress);

        //        CollectionCreator col = new CollectionCreator();
        //        col.ConversionImageQuality = 1;
        //        col.ConversionTileFormat = ImageFormat.Png;
        //        col.ImageQuality = 1;
        //        col.UseOptimizations = true;
        //        col.Create(titles.Select(t => new Microsoft.DeepZoomTools.Image(t)).ToArray(), outputDir);

        //        //UIThread(() => { if (timer != null) timer.Stop(); });
        //    };
        //    worker.RunWorkerCompleted += (o, ea) =>
        //    {
        //        UIThread(() => System.Windows.MessageBox.Show("done"));
        //    };
        //    worker.RunWorkerAsync();
        //}
    }
}